package com.fingard.dsp.bank.directbank.glb01;

import com.fingard.FGBiz;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.ReqPayRecDetail;
import com.fingard.dsp.bank.reqrespobj.single.detail.ReqQrySglBatPayDetail;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.sql.Connection;
import java.util.Map;
import java.util.UUID;

/**
 * @author Alon on 2019-11-17.
 * @version 1.0
 */
public class GLB01SinglePay extends GLB01Base implements ISinglePay {
    private static final String INSERTRECEIPT = "INSERT INTO REQSEQIDMAPPING(URID,BANKCODE,TRANSDATE,REQSEQID,BANKREQSEQID,RESERVE1) values (?,?,?,?,?,?);";
    private static final String SELECTRECEIPT = "SELECT BANKREQSEQID,TRANSDATE,RESERVE1 FROM REQSEQIDMAPPING WHERE REQSEQID=? and BANKCODE=?;";

    @Override
    public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
        //返回ATS的对象
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        RetAtsSglDetail tmpRetAtsDetail = new RetAtsSglDetail();
        XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        Connection conn = FGBiz.getLocalDbConn();
        try {
            String businessCode = "";
            GLB01Header glb01Header = new GLB01Header();
            if (p_req1908.singleDetail.sameBnk.equals("0")) {
                glb01Header.serviceId = "CBE020102";//跨行
                businessCode = "020102";
            } else {
                glb01Header.serviceId = "CBE020100";//同行
                businessCode = "20100";
            }
            glb01Header.serialNo = p_req1908.singleDetail.askNumber;//这个作为银行交易流水号
            glb01Header.reqTime = p_req1908.reqHeader.transTime.replaceAll(" ", "").replaceAll("-", "").replaceAll(":", "");
            writeCommonHeader(xmlWriter, glb01Header);
            //将交易日期,交易代码,和收款方存入数据库，查询交易结果状态的时候使用
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            String tranDate = p_req1908.reqHeader.transTime.split(" ")[0].replaceAll("-", "");
            JDBCHelper.update(conn, INSERTRECEIPT, new Object[]{uuid, p_req1908.reqHeader.bankCode, tranDate, p_req1908.singleDetail.askNumber, p_req1908.singleDetail.recAct, businessCode});

            XElement tmpXElement = new XElement("body", "");
            tmpXElement.addChild(new XElement("payAccount", p_req1908.singleDetail.payAct));//付款账号
            tmpXElement.addChild(new XElement("payAccountName", p_req1908.singleDetail.payName));//付款方户名
            tmpXElement.addChild(new XElement("recAccount", p_req1908.singleDetail.recAct));//收款账号
            tmpXElement.addChild(new XElement("recAccountName", p_req1908.singleDetail.recName));//收款方户名
            if (p_req1908.singleDetail.sameBnk.equals("0")) {
                //跨行
                tmpXElement.addChild(new XElement("recAccountOpenBank", p_req1908.singleDetail.cnapsName));
                tmpXElement.addChild(new XElement("unionBankNo", p_req1908.singleDetail.cnapsCode));//联行号（transferFlag为1时，要上送超网联行号）
                tmpXElement.addChild(new XElement("clearBankNo", p_req1908.singleDetail.cnapsCode));//清算行号（联行号）
                tmpXElement.addChild(new XElement("rmtType", p_req1908.singleDetail.paySpd));//0:普通 目前只支持普通
                tmpXElement.addChild(new XElement("recBankType", "1"));//转账类型(0：行内 1：行外)
                tmpXElement.addChild(new XElement("transferFlag", ""));//转账渠道标志 默认走大小额渠道 值为1：超网渠道
            } else {
                //同行
                tmpXElement.addChild(new XElement("recBankType", "0"));//转账类型(0：行内 1：行外)
            }
            tmpXElement.addChild(new XElement("businessCode", businessCode));//交易代码
            tmpXElement.addChild(new XElement("payAmount", p_req1908.singleDetail.payAmount));//交易金额
            tmpXElement.addChild(new XElement("currencyType", convertCurToBank(p_req1908.singleDetail.payCur)));//币种
            tmpXElement.addChild(new XElement("payRem", p_req1908.singleDetail.abstractATS));//附言(存对账码)
            tmpXElement.addChild(new XElement("pubPriFlag",  p_req1908.singleDetail.isPrivate.equals("1") ? "1" : "0"));//公私标志
            tmpXElement.addChild(new XElement("confirmCode", "9999"));//图形验证码 没有就送‘9999’
            nodeAnalysis(p_req1908.singleDetail.srcXElement,tmpXElement,getCharset());
            xmlWriter.writeXElement(tmpXElement);
            xmlWriter.writeEndDocument();
            //签名
            int headBegin = xmlWriter.toXmlString().indexOf("<head>");
            int bodyEnd = xmlWriter.toXmlString().indexOf("</body>");
            String signData = xmlWriter.toXmlString().substring(headBegin, bodyEnd + 7);
            String signResult = sendHttpRequestToSign(signData);//对报文进行签名

            if (signResult != null && signResult.trim().length() > 0) {
                int signBegin = signResult.indexOf("<sign>");
                int signEnd = signResult.indexOf("</sign>");
                String sign = signResult.substring(signBegin + 6, signEnd);
                xmlWriter.writeElementString("sign", sign);
                xmlWriter.writeEndDocument();
            } else {
                tmpRetAtsDetail.respCode = "-1";
                tmpRetAtsDetail.respInfo = "获取签名数据失败，请求报文发送失败";
                retAts.writeRetDetail(tmpRetAtsDetail);
                return retAts;
            }

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());

            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String returnCode = tmpBkReader.getFirstText("/ebank/head/retCode");
                    String returnMsg = tmpBkReader.getFirstText("/ebank/head/retMessage");
                    if (returnCode != null && "000000".equals(returnCode)) {
                        //90：交易成功 99：交易失败 50：交易结果不确定
                        String orderState = tmpBkReader.getFirstText("/ebank/body/orderState");
                        tmpRetAtsDetail.respCode = "0";
                        if ("90".equals(orderState)) {
                            //90的时候returnMsg为空
                            tmpRetAtsDetail.respInfo = "交易成功";
                        } else {
                            tmpRetAtsDetail.respInfo = returnMsg;
                        }
                        tmpRetAtsDetail.transState = returnCode + "+" + orderState;
                        tmpRetAtsDetail.payInfoCode = tmpRetAtsDetail.transState;
                        tmpRetAtsDetail.reqSeqID = p_req1908.singleDetail.askNumber;
                    } else {
                        tmpRetAtsDetail.respCode = "0";
                        tmpRetAtsDetail.reqSeqID = p_req1908.singleDetail.askNumber;
                        tmpRetAtsDetail.transState = returnCode;
                        tmpRetAtsDetail.payInfoCode = tmpRetAtsDetail.transState;
                        tmpRetAtsDetail.respInfo = returnMsg;
                    }
                } else {
                    tmpRetAtsDetail.respCode = "-1";
                    tmpRetAtsDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetAtsDetail.respCode = "-1";
                tmpRetAtsDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            tmpRetAtsDetail.respCode = "-1";
            tmpRetAtsDetail.respInfo = e.getMessage();
        } finally {
            conn.close();
        }
        retAts.writeRetDetail(tmpRetAtsDetail);
        return retAts;
    }

    @Override
    public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        //返回ATS的对象
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        RetAtsSglDetail tmpRetAtsDetail = new RetAtsSglDetail();
        Connection conn = FGBiz.getLocalDbConn();
        try {
            XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
            GLB01Header glb01Header = new GLB01Header();
            glb01Header.serviceId = "CBE020105";
            glb01Header.serialNo = p_req1944.reqHeader.transSeqID;//这个作为银行交易流水号
            glb01Header.reqTime = p_req1944.reqHeader.transTime.replaceAll(" ", "").replaceAll("-", "").replaceAll(":", "");
            writeCommonHeader(xmlWriter, glb01Header);
            Map<String, Object> map = JDBCHelper.execQuerySingle(conn, SELECTRECEIPT, new Object[]{p_req1944.askNumber, p_req1944.reqHeader.bankCode});
            if (map.size() == 0) {
                tmpRetAtsDetail.respCode = "-1";
                tmpRetAtsDetail.respInfo = "没有这条请求映射的数据！";
                retAts.writeRetDetail(tmpRetAtsDetail);
                return retAts;
            }
            xmlWriter.writeStartElement("body");
            xmlWriter.writeElementString("searchPayAccount", p_req1944.payAct);//付款查询账户
            xmlWriter.writeElementString("searchRecAccount", map.get("BANKREQSEQID").toString());//收款查询账户
            xmlWriter.writeElementString("beginDate", map.get("TRANSDATE").toString());//开始日期
            xmlWriter.writeElementString("endDate", map.get("TRANSDATE").toString());//结束日期
            xmlWriter.writeElementString("orderFlowNo", p_req1944.askNumber);//指令流水号（原交易流水号serialNo）
            xmlWriter.writeElementString("turnPageBeginPos", "1");//翻页数据起始位置
            xmlWriter.writeElementString("orderState", "");//指令状态
            xmlWriter.writeElementString("businessCode", map.get("RESERVE1").toString());//交易代码 行内：020100 行外：020102
            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
//            String[] tmpStrRet = {"", "<?xml  version=\"1.0\"  encoding=\"UTF-8\"  ?><ebank><head><serviceId>CBE020105</serviceId><customerId>CB10016502</customerId><userId>000001</userId><reqTime>20200327114211</reqTime><serialNo>1142112251</serialNo><orderFlowNo>000001JL</orderFlowNo><retCode>000000</retCode><retMessage/></head><body><turnPageTotalNum>0</turnPageTotalNum><list></list></body></ebank>\n"};

            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String returnCode = tmpBkReader.getFirstText("/ebank/head/retCode");
                    String returnMsg = tmpBkReader.getFirstText("/ebank/head/retMessage");
                    if (returnCode != null && "000000".equals(returnCode)) {
                        tmpRetAtsDetail.respCode = "0";
                        tmpRetAtsDetail.reqSeqID = p_req1944.askNumber;
                        //90：交易成功
                        //99：交易失败
                        //50：交易结果不确定
                        if (tmpBkReader.getFirstText("/ebank/body/turnPageTotalNum").equals("0")) {
                            retAts.writeStart();
                            retAts.writeRespCode("-1");
                            retAts.writeRespInfo("查询此流水");
                            retAts.writeEnd();
                            return retAts;
                        } else {
                            String stat = tmpBkReader.getFirstText("/ebank/body/list/row/orderState");
                            tmpRetAtsDetail.transState = returnCode + "+" + stat;//支付状态码
                            tmpRetAtsDetail.payInfoCode = returnCode + "+" + stat;//支付信息码
                            tmpRetAtsDetail.respInfo = returnMsg;
                        }
                    } else {
                        retAts.writeStart();
                        retAts.writeRespCode("-1");
                        retAts.writeRespInfo(returnMsg);
                        retAts.writeEnd();
                        return retAts;
                    }
                } else {
                    tmpRetAtsDetail.respCode = "-1";
                    tmpRetAtsDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetAtsDetail.respCode = "-1";
                tmpRetAtsDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            tmpRetAtsDetail.respCode = "-1";
            tmpRetAtsDetail.respInfo = e.getMessage();
            e.printStackTrace();
        } finally {
            conn.close();
        }
        retAts.writeRetDetail(tmpRetAtsDetail);
        return retAts;
    }

    @Override
    public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
        //返回ATS的对象
        RetAtsSingleBat retAts = new RetAtsSingleBat(p_req1908BAT);
        retAts.reqBatchNO = p_req1908BAT.reqBatchNO;
        retAts.batRespCode = "0";
        retAts.batTransState = "";
        retAts.batPayInfoCode = "";
        while (p_req1908BAT.readRecord()) {
            ReqPayRecDetail tmpDetail = p_req1908BAT.readedDetail;
            ReqSingle req1908 = new ReqSingle(p_req1908BAT.reqHeader);
            req1908.singleDetail = tmpDetail;
            RetAtsSingle eachRet = d_1908_SglPay(req1908);

            retAts.writeRetDetail(eachRet.retDetail);
        }
        retAts.writeAfterDetail();
        return retAts;
    }

    @Override
    public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
        RetAtsSingleBat retAts = new RetAtsSingleBat(p_req1944BAT.reqHeader);
        retAts.reqBatchNO = p_req1944BAT.reqBatchNO;
        try {
            retAts.batRespCode = "0";
            while (p_req1944BAT.readRecord()) {
                ReqQrySglBatPayDetail tmpDetail = p_req1944BAT.readedDetail;
                ReqQrySingle req1944 = new ReqQrySingle(tmpDetail, p_req1944BAT.reqHeader);
                RetAtsSingle resp1944 = d_1944_QrySglPay(req1944);
                retAts.writeRetDetail(resp1944.retDetail);
            }
        } catch (Exception ex) {
            WriteBankLogLn(ex);
            retAts = new RetAtsSingleBat(p_req1944BAT.reqHeader);
            retAts.batRespCode = "-1";
            retAts.batRespInfo = ex.getMessage();
        }

        retAts.writeAfterDetail();
        return retAts;
    }
}
